package asia.huangxi.websocket.socket;

import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.async.ResultCallback;
import com.github.dockerjava.api.model.Frame;
import com.github.dockerjava.core.DefaultDockerClientConfig;
import com.github.dockerjava.core.DockerClientBuilder;
import com.github.dockerjava.core.DockerClientConfig;
import com.github.dockerjava.httpclient5.ApacheDockerHttpClient;
import com.github.dockerjava.transport.DockerHttpClient;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class WebSocketHandler extends TextWebSocketHandler {
    //    private final DockerHelper dockerHelper;
    private final Map<String, OutputStream> dockerOutputStreamMap = new ConcurrentHashMap<>();
    private final String dockerHost = "tcp://172.20.163.108:2375";
    private final String apiVersion = "v1.39";
    private String containerId;
    private DockerClient dockerClient;

//    public WebSocketHandler(DockerHelper dockerHelper) {
//        this.dockerHelper = dockerHelper;
//    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        this.containerId = "239e14a4d33d";
        connect();
        //获得传参
        System.out.println("open= " + session.isOpen());
        exec(session);
        System.out.println("open");
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        System.out.println("message: " + message);
        String containerId = "239e14a4d33d";
        OutputStream out = dockerOutputStreamMap.get(containerId);
        out.write(message.asBytes());
        out.flush();
    }

    public void setDockerInputStreamMap(OutputStream outputStream) {
        this.dockerOutputStreamMap.put(containerId, outputStream);
    }

    private void connect() {
        DockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder()
                .withDockerHost(this.dockerHost)
                .withApiVersion(this.apiVersion)
                .build();
        DockerHttpClient httpClient = new ApacheDockerHttpClient.Builder()
                .dockerHost(config.getDockerHost())
                .maxConnections(100)
                .build();
        DockerClient dockerClient = DockerClientBuilder
                .getInstance(config)
                .withDockerHttpClient(httpClient)
                .build();
        dockerClient.pingCmd().exec();
        this.dockerClient = dockerClient;
    }

    //    @Async
    public void exec(WebSocketSession session/*, ChatEndpoint handler*/) throws InterruptedException, IOException {

        var id = this.dockerClient.execCreateCmd("239e14a4d33d")
                .withCmd("/bin/bash")
                .withTty(true)
                .withAttachStderr(true)
                .withAttachStdin(true)
                .withAttachStdout(true)
                .exec()
                .getId();

        PipedOutputStream pipedOutputStream = new PipedOutputStream();
        PipedInputStream pipedInputStream = new PipedInputStream(pipedOutputStream);


        this.dockerOutputStreamMap.put(containerId, pipedOutputStream);
//        this.dockerClient.resizeExecCmd(id).withSize(Integer.parseInt(session.getAttributes().get("height").toString()), Integer.parseInt(session.getAttributes().get("width").toString()));
        new Thread(() -> {
            try {
                this.dockerClient.execStartCmd(id)
                        .withDetach(false)
                        .withTty(true)
                        .withStdIn(pipedInputStream)
                        .exec(new ResultCallback.Adapter<>() {
                            @Override
                            public void onNext(Frame object) {
                                try {
                                    System.out.println("object: " + object);
                                    System.out.println("open= " + session.isOpen());
                                    session.sendMessage(new TextMessage(new String(object.getPayload(), StandardCharsets.UTF_8)));
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                            }
                        }).awaitCompletion();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

    }
}
